/*************************************************************************
      > File Name: udpserver.hpp
      > Author: 小和尚念经敲木鱼
      > Mail:  
      > Created Time: Thu 04 Jul 2024 12:07:23 PM CST
 ***********************************************************************/

#include<iostream>
using namespace std;
/************************************************************************
* 文件说明
************************************************************************/
int main(int agc,char * agv[])
{

 
 
  return 0;
}
/******************************end of file******************************/
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <thread>
#include <mutex>
#include <vector>
#include "log.hpp"
#include "Common.hpp"
const static int defaultfd = -1;


struct usermessage
{
    struct sockaddr_in sockaddr;
    socklen_t socklen;
};

class Udpserver
{

public:
    Udpserver(uint16_t port)
        : _socketfd(defaultfd), _prot(port), _isrunning(false)
    {
        EnableFile();
        _socklen = sizeof(_peer);
        InitServer();
    }
    void InitServer()
    {
        _socketfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_socketfd < 0)
        {
            LOG(WARNING, "%s", "sockfd创建失败");
        }
        LOG(INFO, "%s", "sock创建成功");
        // 填充sockaddr_in结构
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = AF_INET;    // 设置家族协议
        local.sin_port = htons(_prot); // 设置端口号 换成网络序列
        // port要经过网络传输给对面，先到网络，_port：主机序列-> 主机序列，转成网络序列
        // a. 字符串风格的点分十进制的IP地址转成 4 字节IP
        // b. 主机序列，转成网络序列
        // in_addr_t inet_addr(const char *cp) -> 同时完成 a & b
        // local.sin_addr.s_addr = inet_addr(_ip.c_str()); // "192.168.3.1" -> 字符串风格的点分十进制的IP地址 -> 4字节IP
        local.sin_addr.s_addr = INADDR_ANY; // 随机ip地址 一般不能绑定确定ip地址
        LOG(INFO,"%s","本地协议,端口号,ip地址绑定成功");
	// 开始绑定
        int n = bind(_socketfd, (struct sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            LOG(FATAL, "%s", "bind error");
            exit(BIND_ERROR);
        }
        LOG(INFO, "%s", "bind success");
        _isrunning = true;
    }

    void receive()
    {
        while (_isrunning)
        {
            char Inbuffer[1024] = {0}; // 初始化缓冲区
            usermessage user;
            user.socklen=sizeof(user.sockaddr);
                ssize_t n = recvfrom(_socketfd, Inbuffer, sizeof(Inbuffer) - 1, 06++6++-, (struct sockaddr *)&user.sockaddr, &user.socklen);
                if (n > 0)
                {
                    Inbuffer[n] = 0;
                    std::lock_guard<std::mutex> lock(_peerMutex);
                    _userspeer.push_back(user);
                    std::cout << "client says:" << Inbuffer << std::endl;
                }
                else
                {
                    perror("recvfrom error");
                }
        }
    }
    void sent()
    {
        while (_isrunning)
        {
            std::string message;
            std::cout << "server: ";
            std::cin >> message;
            std::lock_guard<std::mutex> lock(_peerMutex);
            ssize_t sent = sendto(_socketfd, message.c_str(), message.size(), 0, (struct sockaddr *)&_peer, _socklen);
            if (sent == -1)
            {
                perror("sendto error");
            }
            std::cout << std::endl;
        }
    }
    void Start()
    {
        std::thread recvThread(&Udpserver::receive, this);
        std::thread sendThread(&Udpserver::sent, this);

        recvThread.detach();
        sendThread.detach();//线程分离
        while (_isrunning)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        close(_socketfd);
    }

private:
    int _socketfd;
    uint16_t _prot;
    bool _isrunning;
    //////////////////
    struct sockaddr_in _peer;
    socklen_t _socklen;
    //////////////////锁
    std::mutex _peerMutex;
    std::mutex _streamMutex;
    ///////存放所有用户的ip地址
    std::vector<usermessage> _userspeer;
};
